package gui;

import java.awt.Color;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.BorderFactory;
import javax.swing.JLabel;

/**
 * @author Ramy Refky 
 * */
public class WireSegment extends JLabel implements MouseListener,MouseMotionListener{

	private static final long serialVersionUID = 1L;
	
	Point startPoint;
	Point endPoint;
	Wire w;
	MainGui mg;
	
	/**
	 * Constructor initializes WireSegment Class, which is a component of a wire.
	 * @param MainGui, Wire, StartPoint, EndPoint
	 * */
	public WireSegment(MainGui mg,Wire w,Point startPoint, Point endPoint){
		
		this.mg=mg;
		this.w=w;
		startPoint.x-=4;
		startPoint.y-=4;
		this.startPoint=startPoint;
		this.endPoint=endPoint;
		
		Rectangle wireRect= new Rectangle();
		wireRect.setFrameFromDiagonal(startPoint,endPoint);
		wireRect.translate(0,2);
		setBounds(wireRect);
		startPoint.x+=4;
		startPoint.y+=4;
		
		setBorder(BorderFactory.createLineBorder(Color.black,4));
		setOpaque(true);
		setVisible(true);
		this.addMouseListener(this);
		this.addMouseMotionListener(this);
		
		repaint();
	}
	/**
	 * Returns the parent wire of this WireSegment.
	 * @return Wire
	 * */
	public Wire getWire(){
		return w;
	} 
	/**
	 * Returns the starting point of this WireSegment.
	 * @return Point
	 * */
	public Point getStartPoint(){
		return startPoint;
	}
	/**
	 * Returns the ending point of this WireSegment.
	 * @return Point
	 * */
	public Point getEndPoint(){
		return endPoint;
	}
	/**
	 * Sets the starting point of this WireSegment.
	 * */
	public void setStartPoint(Point startPoint){
		this.startPoint=startPoint;
	}
	/**
	 * Sets the ending point of this WireSegment.
	 * */
	public void setEndPoint(Point endPoint){
		this.endPoint=endPoint;
	}
	/**
	 * Checks if this WireSegment can be moved for fine-tuning. If it is directly connected to
	 * a ComponentPin, it cannot be moved.
	 * @return Boolean
	 * */
	public Boolean isMovableSegment(){
		boolean movable=false;
		if(!w.getStartPoint().equals(getStartPoint()) && !w.getEndPoint().equals(getEndPoint())){
			movable=true;
		}
		return movable;
	}
	@Override
	public void mouseClicked(MouseEvent arg0) {}
	@Override
	public void mouseEntered(MouseEvent e) {
		if(mg.getActions().getCurrentAction()==7){
			if(isMovableSegment()){
				setBorder(BorderFactory.createLineBorder(Color.green,4));
			}
		}
		if(mg.getActions().getCurrentAction()==17){
			for(int i=0;i<w.getWireSegments().size();i++){
				w.getWireSegments().get(i).setBorder(BorderFactory.createLineBorder(Color.red,4));
			}
		}
	}
	@Override
	public void mouseExited(MouseEvent e) {
		for(int i=0;i<w.getWireSegments().size();i++){
			w.getWireSegments().get(i).setBorder(BorderFactory.createLineBorder(Color.black,4));
		}
	}
	@Override
	public void mousePressed(MouseEvent arg0) {
		if(mg.getActions().getCurrentAction()==17){
			mg.getWorkArea().getWiringGrid().deleteWire(w);
			mg.getWorkArea().drawIntersections();
			mg.getWorkArea().drawWireGroupDisplays();
		}
	}
	@Override
	public void mouseReleased(MouseEvent arg0) {
		setBorder(BorderFactory.createLineBorder(Color.black,4));
		w.maintainWire();
		mg.getWorkArea().drawIntersections();
		mg.getWorkArea().drawWireGroupDisplays();
	}
	@Override
	public void mouseDragged(MouseEvent arg0) {
		if(mg.getActions().getCurrentAction()==7){
			if(isMovableSegment()){
				setBorder(BorderFactory.createLineBorder(Color.green,4));
				if(w.getWireSegments().size()==3){
					if((getX()+arg0.getPoint().x)>w.getStartPoint().x+5 && 
							(getX()+arg0.getPoint().x)<w.getEndPoint().x-5){
						
						WireSegment ws1=w.getWireSegmentEndingAt(getStartPoint());
						WireSegment ws2=w.getWireSegmentStartingAt(getEndPoint());
						
						ws1.setBounds(ws1.getX(),ws1.getY(),getX()+arg0.getPoint().x-ws1.getX()+4,ws1.getHeight());
						Point ws1ep=ws1.getEndPoint();
						ws1ep.x=getX()+arg0.getPoint().x+4;
						ws1.setEndPoint(ws1ep);
						
						ws2.setBounds(getX()+arg0.getPoint().x,ws2.getY(),ws2.getEndPoint().x-getX()-arg0.getPoint().x+4,ws2.getHeight());
						Point ws2sp=ws2.getStartPoint();
						ws2sp.x=getX()+arg0.getPoint().x+4;
						ws2.setStartPoint(ws2sp);
						
						Point wsp=getStartPoint();
						wsp.x=getX()+arg0.getPoint().x+4;
						setStartPoint(wsp);
						
						Point wep=getEndPoint();
						wep.x=getX()+arg0.getPoint().x+4;
						setEndPoint(wep);
						setBounds(getX()+arg0.getPoint().x,getY(),getWidth(),getHeight());
					}
				}else{
					//parent wire contains 5 wire segments instead of only 3
					if(w.getWireSegments().indexOf(this)==1){
						if((getX()+arg0.getPoint().x)>w.getStartPoint().x+5 &&
								(getX()+arg0.getPoint().x)<mg.getWorkArea().getWidth()-10){
							
							WireSegment ws1=w.getWireSegments().get(0);
							WireSegment ws2=w.getWireSegments().get(2);
							
							ws1.setBounds(ws1.getX(),ws1.getY(),getX()+arg0.getPoint().x-ws1.getX()+4,ws1.getHeight());
							Point ws1ep=ws1.getEndPoint();
							ws1ep.x=getX()+arg0.getPoint().x+4;
							ws1.setEndPoint(ws1ep);
							
							ws2.setBounds(ws2.getX(),ws2.getY(),getX()+arg0.getPoint().x-ws2.getX()+4,ws2.getHeight());
							Point ws2sp=ws2.getStartPoint();
							ws2sp.x=getX()+arg0.getPoint().x+4;
							ws2.setStartPoint(ws2sp);
							
							Point wsp=getStartPoint();
							wsp.x=getX()+arg0.getPoint().x+4;
							setStartPoint(wsp);
							
							Point wep=getEndPoint();
							wep.x=getX()+arg0.getPoint().x+4;
							setEndPoint(wep);
							setBounds(getX()+arg0.getPoint().x,getY(),getWidth(),getHeight());
						}
					}else{
						if(w.getWireSegments().indexOf(this)==3){
							if((getX()+arg0.getPoint().x)<w.getEndPoint().x-5 && (getX()+arg0.getPoint().x)>0 ){
								WireSegment ws1=w.getWireSegments().get(2);
								WireSegment ws2=w.getWireSegments().get(4);
								
								ws1.setBounds(getX()+arg0.getPoint().x,ws1.getY(),ws1.getStartPoint().x-getX()-arg0.getPoint().x-4,ws1.getHeight());
								Point ws1ep=ws1.getEndPoint();
								ws1ep.x=getX()+arg0.getPoint().x+4;
								ws1.setEndPoint(ws1ep);
								
								ws2.setBounds(getX()+arg0.getPoint().x,ws2.getY(),ws2.getEndPoint().x-getX()-arg0.getPoint().x+4,ws2.getHeight());
								Point ws2sp=ws2.getStartPoint();
								ws2sp.x=getX()+arg0.getPoint().x+4;
								ws2.setStartPoint(ws2sp);
								
								Point wsp=getStartPoint();
								wsp.x=getX()+arg0.getPoint().x+4;
								setStartPoint(wsp);
								
								Point wep=getEndPoint();
								wep.x=getX()+arg0.getPoint().x+4;
								setEndPoint(wep);
								setBounds(getX()+arg0.getPoint().x,getY(),getWidth(),getHeight());
							}
						}
						else{
							if(w.getWireSegments().indexOf(this)==2){
								
								if((getY()+arg0.getPoint().y)<mg.getWorkArea().getHeight()
										&& (getY()+arg0.getPoint().y)>0 ){
									
									WireSegment ws1=w.getWireSegments().get(1);
									WireSegment ws2=w.getWireSegments().get(3);
								
									Point ws1ep=ws1.getEndPoint();
									ws1ep.y=getY()+arg0.getPoint().y+4;
									ws1ep.x=ws1.getStartPoint().x-4;
									ws1.setEndPoint(ws1ep);
								
									Rectangle dimension1= new Rectangle();
									dimension1.setFrameFromDiagonal(ws1.getEndPoint(),ws1.getStartPoint());
									ws1.setBounds(dimension1);
								
									Point ws2sp=ws2.getStartPoint();
									ws2sp.y=getY()+arg0.getPoint().y+4;
									ws2sp.x=ws2.getEndPoint().x-4;
									ws2.setStartPoint(ws2sp);
								
									Rectangle dimension2= new Rectangle();
									dimension2.setFrameFromDiagonal(ws2.getEndPoint(),ws2.getStartPoint());
									ws2.setBounds(dimension2);
								
									Point wsp=getStartPoint();
									wsp.y=getY()+arg0.getPoint().y+4;
									setStartPoint(wsp);
								
									Point wep=getEndPoint();
									wep.y=getY()+arg0.getPoint().y+4;
									setEndPoint(wep);
									setBounds(getX(),getY()+arg0.getPoint().y,getWidth(),getHeight());	
								}	
							}
						}
					}
				}
			}
		}
	}
	@Override
	public void mouseMoved(MouseEvent arg0) {}
	
}
